import React, { useState, useCallback, useEffect, useMemo } from 'react';
import { Common } from 'UtilsCommon';
import { useGetDataSourceOptions } from 'UseHooks';
import Base from './base';
import Components from 'Components';

const getOptions = (property) => {
    Base.setValueTextName(property);

    const { dataSource, valueName, textName } = property;

    const options = [];

    dataSource.forEach(d => {
        const value = d[valueName];
        const label = d[textName];
        options.push({ value, label });
    });

    return options;
};

const renderItem = (property, item, index, value, onChange, pageId) => {
    const { itemStyle, textStyle, onTextStyle, onImgUrl, offImgUrl } = property;

    const checked = value.includes(item.value);

    let expandProperty;
    if (property.properties) {
        expandProperty = Common.arrayFirst(property.properties, f => Common.isEquals(f.name, item.value));
        if (expandProperty != null) {
            expandProperty.isVisible = checked;
            expandProperty.setIsVisible && expandProperty.setIsVisible(checked);
        }
    }

    const checkStyle = property.checkStyle;
    checkStyle.backgroundImage = checked ? onImgUrl : offImgUrl;

    const textStyle2 = checked ? onTextStyle || textStyle : textStyle;

    return <React.Fragment key={index}>
        <div style={Base.setStyle(itemStyle)} key={index} className='buttonActive' onClick={e => onChange(e, item)}>
            <div style={Base.setStyle(checkStyle)}></div>
            <div style={Base.setStyle(textStyle2)} dangerouslySetInnerHTML={{ __html: item.label }}></div>
        </div>
        {expandProperty && <Components.PropertyItem property={expandProperty} view={property} pageId={pageId} />}
    </React.Fragment>;
};

const valueChange = (property, view, value) => {
    if (property.valueChange) property.valueChange(value, Base.getSelectData(property, value));

    if (property.valueVisibleProperties) Base.setValueVisibleProperties(property, view, value);
};

const getValue = (property, v) => {
    if (Common.isNullOrEmpty(v)) return [];

    if (Common.isArray(v)) return v;

    if (property.isJson) return JSON.parse(v);
    return v.split(',');
};

const judgeNullable = (property, value, pageAxis) => {
    if (value.length === 0) return property.nullTipMessage;
    else if (property.minLength > value.length) return property.minTipMessage;

    return '';
};

export default React.memo((props) => {
    const { property, view, pageAxis, pageId } = Base.getProps(props);

    const initValue = useMemo(() => getValue(property, property.value), [property]);

    const [value, setValue] = useState(initValue);
    const [isVisible, setIsVisible] = useState(property.isVisible !== false);

    const [options, setOptions] = useGetDataSourceOptions(property, view, pageAxis, getOptions, property.id);

    const onChange = useCallback((e, m) => {
        if (property.isSingle) setValue([m.value]);
        else {
            let value2 = value;
            if (value2.includes(m.value)) value2 = value.filter(f => !Common.isEquals(f, m.value));
            else {
                if (property.maxLength > 0 && value.length >= property.maxLength) return;

                value2 = value2.map(m => m);
                value2.push(m.value);
            }
            if (property.expandSetValue) value2 = property.expandSetValue(value2, m.value);
            setValue(value2);
        }
    }, [property, setValue, value]);

    useEffect(() => {
        valueChange(property, view, value);
    }, [property, view, value]);

    property.setIsVisible = (v) => { property.isVisible = v; setIsVisible(v); };
    property.setValue = (v) => setValue(getValue(property, v));
    property.getValue = () => Base.getValue(property, value);
    property.refreshOptions = (v) => setOptions(getOptions(property, view, pageAxis));
    property.judgeNullable = () => judgeNullable(property, value, pageAxis);

    if (!isVisible) return null;

    const { style, labelStyle, label, listStyle, isRed, isAddColon, isNullable } = property;

    const isRed2 = property.isRed2 || (isNullable === false && isRed);

    const label2 = property.isLabel === false ? '' : label;

    return <div style={Base.setStyle(style)}>
        {label2 && <div style={Base.setStyle(labelStyle)}>
            {isRed2 ? <span style={{ color: 'red', position: 'relative', paddingRight: '0.125rem', top: '0.125rem' }}>*</span> : ''}
            <span dangerouslySetInnerHTML={{ __html: label2 }}></span>{isAddColon ? '：' : ''}
        </div>}
        <div style={Base.setStyle(listStyle)}>
            {options.map((m, i) => renderItem(property, m, i, value, onChange, pageId))}
        </div>
    </div>;
});